--- @coding utf8

---@class _xclassEnv
---@field inited boolean 是否已经完成初始化
---@field cls_name2type table<string, XClassType>
_xclassEnv = _xclassEnv or {}

---@brief 类型类
---@class XClassType
---@field __xclass_name string : 类名
---@field __xclass_module string : 模块信息,用于热更新和重复注册校验
---@field __xclass_super XClassType : 基类类类型
---@field _constructor function|nil : 由具体的类类型实现(不实现则不调用)
---@field _destructor function|nil : (暂不支持)析构函数，默认绑定到__gc上

---@brief XClassObject基础接口
---@class XClassObject
---@field _constructor function(...)

---@brief 初始化xclass环境支持
local function init_xclassEnv()
    if _xclassEnv.inited ~= true then
        _xclassEnv = {
            inited = true,
            cls_name2type = {},  -- 记录全部的类型名到类型类(类注册表)
        }
    end
end

--- 初始化xclass环境变量
init_xclassEnv()

---@brief xclass对象构造函数入口
---@param cls XClassType
---@return XClassObject
local function xclass_object_constructor(cls, ...)
    local object = {}
    setmetatable(object, {
        __index = cls
    })
    -- 定义了构造函数一定要调用构造函数
    if nil ~= cls._constructor then
        object:_constructor(...)
    end
    return object
end

---@brief 类类型构造函数(不存在则创建，已经存在返回)
---@param class_name string
---@param super_class_type XClassType|nil
---@return XClassType
local function xclass_type_constructor(class_name, super_class_type)
    local dinfo = debug.getinfo(2, "S")
    local module = dinfo.short_src
    -- 获取已注册的类型类
    ---@type XClassType
    local class_type = _xclassEnv.cls_name2type[class_name]
    -- 新增
    if nil == class_type then
        class_type = {
            __xclass_name = class_name,
            __xclass_super = super_class_type,
            __xclass_module = module,
        }
        _xclassEnv.cls_name2type[class_name] = class_type
        -- 类类型原表设置
        setmetatable(class_type, {
            __call = xclass_object_constructor,  -- 构造函数语法糖
            __index = super_class_type,          -- 继承基类属性
        })
        --print("reg new xclass:", class_name)
    else  -- 修改
        if module ~= class_type.__xclass_module then
            error(string.format("xclass_type update faild, invalid xclass_module: xclass_name=%s,old_module=%s,new_module=%s",
                class_name, class_type.__xclass_module, module))
        end
        --print("update xclass:", class_name)
    end
    return class_type
end

---@brief 定义一个类
---@param cls_name string
---@param super_cls_type XClassType|nil
local function xclass(cls_name, super_cls_type)
    local cls = xclass_type_constructor(cls_name, super_cls_type)
    return cls
end


-- 导出给全局命名文件
_G.xclass = xclass

-- 模块导出
return xclass
